﻿/*
* Slickflow 工作流引擎遵循LGPL协议，也可联系作者商业授权并获取技术支持；
* 除此之外的使用则视为不正当使用，请您务必避免由此带来的商业版权纠纷。
* 
The Slickflow project.
Copyright (C) 2014  .NET Workflow Engine Library

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, you can access the official
web page about lgpl: https://www.gnu.org/licenses/lgpl.html
*/

using System;
using System.Collections.Generic;
using System.Linq;
using Sharp.Domain.PlatformBoundedContext.WorkFlowModule.Aggregates;
using Sharp.Domain.PlatformBoundedContext.WorkFlowModule.Engine.Business.EntitySQLServer;
using Sharp.Domain.PlatformBoundedContext.WorkFlowModule.Engine.Common;
using Sharp.Domain.PlatformBoundedContext.WorkFlowModule.Engine.Xpdl;
using Sharp.Domain.Repositories;
using Sharp.Infrastructure.IoC;

namespace Sharp.Domain.PlatformBoundedContext.WorkFlowModule.Engine.Business.Manager
{
    public interface IActivityInstanceManager
    {
        /// <summary>
        /// 根据ID获取活动实例
        /// </summary>
        /// <param name="activityInstanceID"></param>
        /// <returns></returns>
        ActivityInstanceEntity GetById(int activityInstanceID);

        /// <summary>
        /// 获取流程当前运行节点信息
        /// </summary>
        /// <param name="runner">执行者</param>
        /// <returns>活动实例</returns>
        ActivityInstanceEntity GetRunningNode(WfAppRunner runner);

        /// <summary>
        /// 获取流程当前运行节点信息
        /// </summary>
        /// <param name="runner">执行者</param>
        /// <param name="taskView">任务视图</param>
        /// <returns>活动实例</returns>
        ActivityInstanceEntity GetRunningNode(WfAppRunner runner,
            out TaskEntity taskView);

        /// <summary>
        /// 判断任务所属
        /// </summary>
        /// <param name="entity">活动实例</param>
        /// <param name="userID">用户ID</param>
        /// <returns>标识</returns>
        bool IsMineTask(ActivityInstanceEntity entity,
            string userID);

        /// <summary>
        /// 获取活动实例列表
        /// </summary>
        /// <param name="processInstanceID">流程实例ID</param>
        /// <returns>活动实例列表</returns>
        IList<ActivityInstanceEntity> GetActivityInstances(int processInstanceID);

        /// <summary>
        /// 活动实例列表
        /// </summary>
        /// <param name="appInstanceID">应用实例ID</param>
        /// <param name="processGUID">流程GUID</param>
        /// <param name="activityGUID">活动GUID</param>
        /// <returns>活动实例列表</returns>
        IList<ActivityInstanceEntity> GetActivityInstance(string appInstanceID,
            string processGUID,
            string activityGUID);

        /// <summary>
        /// 获取运行状态的活动实例
        /// </summary>
        /// <param name="processInstanceID">流程实例ID</param>
        /// <param name="activityGUID">活动GUID</param>
        
        /// <returns>活动实例</returns>
        ActivityInstanceEntity GetActivityRunning(int processInstanceID,
            string activityGUID);

        /// <summary>
        /// 根据状态获取活动实例
        /// </summary>
        /// <param name="processInstanceID">流程实例ID</param>
        /// <param name="activityGUID">活动GUID</param>
        /// <param name="activityState">活动状态</param>
        /// <returns>活动实例</returns>
        ActivityInstanceEntity GetActivityByState(int processInstanceID,
            string activityGUID,
            ActivityStateEnum activityState);

        /// <summary>
        /// 获取完成状态的活动实例
        /// </summary>
        /// <param name="processInstanceID">流程实例ID</param>
        /// <param name="activityGUID">活动GUID</param>
        /// <returns>活动实例实体</returns>
        ActivityInstanceEntity GetActivityCompleted(int processInstanceID,
            string activityGUID);

        /// <summary>
        /// 由任务ID获取活动实例信息
        /// </summary>
        /// <param name="taskID">任务ID</param> 
        /// <returns>活动实例实体</returns>
        ActivityInstanceEntity GetByTask(int taskID);

        /// <summary>
        /// 获取流程实例中运行的活动节点
        /// </summary>
        /// <param name="appInstanceID">应用实例ID</param>
        /// <param name="processGUID">流程GUID</param>
        /// <returns>活动实例列表</returns>
        IEnumerable<ActivityInstanceEntity> GetRunningActivityInstanceList(string appInstanceID,
            string processGUID);

        /// <summary>
        /// 获取已经运行完成的节点
        /// </summary>
        /// <param name="appInstanceID">应用实例ID</param>
        /// <param name="processGUID">流程GUID</param>
        /// <returns></returns>
        List<ActivityInstanceEntity> GetCompletedActivityInstanceList(string appInstanceID,
            string processGUID);

        /// <summary>
        /// 获取主节点下已经完成的子节点列表
        /// </summary>
        /// <param name="mainActivityInstanceID">主活动实例ID</param>
        /// <returns></returns>
        List<ActivityInstanceEntity> GetCompletedMultipleInstanceList(int mainActivityInstanceID);

        /// <summary>
        /// 获取会签节点的多实例节点
        /// </summary>
        /// <param name="mainActivityInstanceID">会签节点</param>
        /// <param name="processInstanceID">流程实例ID</param>
        /// <param name="activityState">活动状态</param>
        /// <returns>活动实例列表</returns>
        List<ActivityInstanceEntity> GetActivityMulitipleInstanceWithState(int mainActivityInstanceID, int processInstanceID, ActivityStateEnum activityState);

        /// <summary>
        /// 获取会签节点的多实例节点
        /// </summary>
        /// <param name="mainActivityInstanceID">会签节点</param>
        /// <param name="processInstanceID">流程实例ID</param>

        /// <returns>活动实例列表</returns>
        List<ActivityInstanceEntity> GetActivityMultipleInstance(int mainActivityInstanceID,
            int processInstanceID);

        /// <summary>
        /// 获取多实例主节点下的子节点列表
        /// </summary>
        /// <param name="mainActivityInstanceID">主节点活动实例ID</param>
        /// <param name="processInstanceID">流程实例ID</param>
        /// <param name="activityState">活动状态</param>
        /// <returns>活动实例列表</returns>
        List<ActivityInstanceEntity> GetActivityMultipleInstance(int mainActivityInstanceID, int processInstanceID, ActivityStateEnum activityState);

        /// <summary>
        /// 查询实例节点的前置节点
        /// </summary>
        /// <param name="mainActivityInstanceID"></param>
        /// <param name="activityInstanceID"></param>
        /// <param name="completeOrder"></param>
        /// <returns></returns>
        ActivityInstanceEntity GetPreviousOfMultipleInstanceNode(int mainActivityInstanceID,
            int activityInstanceID,
            double completeOrder);

        /// <summary>
        /// 查询分支实例的个数
        /// </summary>
        /// <param name="splitActivityGUID">节点GUID</param>
        /// <param name="processInstanceID">流程实例ID</param>
        /// <returns>网关实例数目</returns>
        int GetInstanceGatewayCount(string splitActivityGUID,
            int processInstanceID);

        /// <summary>
        /// 创建活动实例的对象
        /// </summary>
        /// <param name="appName">应用名称</param>
        /// <param name="appInstanceID">应用实例ID</param>
        /// <param name="processInstanceID">流程实例ID</param>
        /// <param name="activity">活动</param>
        /// <param name="runner">运行者</param>
        /// <returns>活动实例实体</returns>
        ActivityInstanceEntity CreateActivityInstanceObject(string appName,
            string appInstanceID,
            int processInstanceID,
            ActivityEntity activity,
            WfAppRunner runner);

        /// <summary>
        /// 根据主节点复制子节点
        /// </summary>
        /// <param name="main">活动实例</param>
        /// <returns>活动实例</returns>
        ActivityInstanceEntity CreateActivityInstanceObject(ActivityInstanceEntity main);

        /// <summary>
        /// 创建活动实例的对象
        /// </summary>
        /// <param name="appName">应用名称</param>
        /// <param name="appInstanceID">应用实例ID</param>
        /// <param name="processInstanceID">流程实例ID</param>
        /// <param name="activity">活动</param>
        /// <param name="backwardType">退回类型</param>
        /// <param name="backSrcActivityInstanceID">退回源活动实例ID</param>
        /// <param name="runner">执行者</param>
        /// <returns>活动实例</returns>
        ActivityInstanceEntity CreateBackwardActivityInstanceObject(string appName,
            string appInstanceID,
            int processInstanceID,
            ActivityEntity activity,
            BackwardTypeEnum backwardType,
            int backSrcActivityInstanceID,
            WfAppRunner runner);

        /// <summary>
        /// 更新活动节点的Token数目
        /// </summary>
        /// <param name="activityInstanceID">活动实例ID</param>
        /// <param name="runner">运行者</param>
        void IncreaseTokensHad(int activityInstanceID,
            WfAppRunner runner);

        /// <summary>
        /// 活动实例被读取
        /// </summary>
        /// <param name="activityInstanceID">活动实例ID</param>
        /// <param name="runner">运行者</param>
        void SetActivityRead(int activityInstanceID, WfAppRunner runner);

        /// <summary>
        /// 撤销活动实例
        /// </summary>
        /// <param name="activityInstanceID">活动实例ID</param>
        /// <param name="runner">运行者</param>
        void Withdraw(int activityInstanceID, WfAppRunner runner);

        /// <summary>
        /// 退回活动实例
        /// </summary>
        /// <param name="activityInstanceID">活动实例ID</param>
        /// <param name="runner">运行者</param>
        void SendBack(int activityInstanceID, WfAppRunner runner);

        /// <summary>
        /// 活动实例完成
        /// </summary>
        /// <param name="activityInstanceID">活动实例ID</param>
        /// <param name="runner">运行者</param>
        void Complete(int activityInstanceID,
            WfAppRunner runner);

        /// <summary>
        /// 插入活动实例
        /// </summary>
        /// <param name="entity">实体</param>
        
        /// <returns>新的自增长ID键值</returns>
        int Insert(ActivityInstanceEntity entity);

        /// <summary>
        /// 更新活动实例
        /// </summary>
        /// <param name="entity">活动实例实体</param>
        void Update(ActivityInstanceEntity entity);

        /// <summary>
        /// 更新会签节点中未办理完成的节点状态
        /// </summary>
        /// <param name="mainActivityInstanceID">主节点ID</param>
        /// <param name="runner">执行者</param>
        void CancelUnCompletedMultipleInstance(int mainActivityInstanceID, WfAppRunner runner);

        /// <summary>
        /// 撤销主节点及其下面的多实例子节点
        /// </summary>
        /// <param name="mainActivityInstanceID">主节点ID</param>
        /// <param name="runner">执行者</param>
        void WithdrawMainIncludedChildNodes(int mainActivityInstanceID,
            WfAppRunner runner);

        /// <summary>
        /// 重新使节点处于挂起状态
        /// 说明：会签最后一个子节点撤销时候用到
        /// </summary>
        /// <param name="activityInstanceID">活动实例节点ID</param>
        /// <param name="runner">执行者</param>
        void Resuspend(int activityInstanceID,
            WfAppRunner runner);

        /// <summary>
        /// 删除活动实例
        /// </summary>
        /// <param name="activityInstanceID">活动实例ID</param>
        void Delete(int activityInstanceID);
    }

    /// <summary>
    /// 活动实例管理类
    /// </summary>
    public class ActivityInstanceManager : IActivityInstanceManager
    {
        private IRepositoryContext _context;
        private IActivityInstanceEntityRepository _activityInstanceEntityRepository;
        private ITransitionInstanceEntityRepository _transitionInstanceEntityRepository;
        public ActivityInstanceManager(IRepositoryContext context,
            IActivityInstanceEntityRepository activityInstanceEntityRepository,
            ITransitionInstanceEntityRepository transitionInstanceEntityRepository)
        {
            _context = context;
            _activityInstanceEntityRepository = activityInstanceEntityRepository;
            _transitionInstanceEntityRepository = transitionInstanceEntityRepository;
        }

        #region ActivityInstanceManager get data

        /// <summary>
        /// 根据ID获取活动实例
        /// </summary>
        /// <param name="activityInstanceID"></param>
        /// <returns></returns>
        public ActivityInstanceEntity GetById(int activityInstanceID)
        {
            var entity = _activityInstanceEntityRepository.Get(activityInstanceID);
            return entity;
        }



        /// <summary>
        /// 获取流程当前运行节点信息
        /// </summary>
        /// <param name="runner">执行者</param>
        /// <returns>活动实例</returns>
        public ActivityInstanceEntity GetRunningNode(WfAppRunner runner)
        {
            var appInstanceID = runner.AppInstanceID;
            var processGUID = runner.ProcessGUID;
            var taskID = runner.TaskID;

            //如果流程在运行状态，则返回运行时信息
            TaskEntity task = null;

            var entity = GetRunningNode(runner, out task);

            return entity;
        }

        /// <summary>
        /// 获取流程当前运行节点信息
        /// </summary>
        /// <param name="runner">执行者</param>
        /// <param name="taskView">任务视图</param>
        /// <returns>活动实例</returns>
        public ActivityInstanceEntity GetRunningNode(WfAppRunner runner,
            out TaskEntity taskView)
        {
            var appInstanceID = runner.AppInstanceID;
            var processGUID = runner.ProcessGUID;
            var taskID = runner.TaskID;

            taskView = null;
            ActivityInstanceEntity activityInstance = null;

            //如果流程在运行状态，则返回运行时信息
            var tm = ServiceLocator.Instance.GetService<ITaskManager>();

            var activityInstanceList = GetRunningActivityInstanceList(runner.AppInstanceID, runner.ProcessGUID).ToList();

            if ((activityInstanceList != null) && (activityInstanceList.Count == 1))
            {
                activityInstance = activityInstanceList[0];
                taskView = tm.GetTaskOfMine(activityInstance.Id, runner.UserID);
            }
            else if (activityInstanceList.Count > 0)
            {
                if (runner.TaskID != null && runner.TaskID.Value != 0)
                {
                    taskView = tm.GetTaskView(taskID.Value);

                    foreach (var ai in activityInstanceList)
                    {
                        if (ai.Id == taskView.ActivityInstanceID)
                        {
                            activityInstance = ai;
                            break;
                        }
                    }

                    //判断是否有并行节点存在，如果有并行节点存在，取并行节点的主节点（并行会签）
                    if (activityInstance == null && activityInstanceList[0].MIHostActivityInstanceID != null)
                    {
                        var mainActivityInstanceID = activityInstanceList[0].MIHostActivityInstanceID;
                        activityInstance = GetById(mainActivityInstanceID.Value);
                    }
                }
                else
                {
                    //并行模式处理
                    //根据当前执行者身份取出(他或她)要办理的活动实例（并行模式下有多个处于待办或运行状态的节点）
                    foreach (var ai in activityInstanceList)
                    {
                        if (ai.AssignedToUserIDs == runner.UserID)
                        {
                            activityInstance = ai;
                            break;
                        }
                    }

                    if (activityInstance != null)
                    {
                        //获取taskview
                        taskView = tm.GetTaskOfMine(activityInstance.Id, runner.UserID);
                    }
                    else
                    {
                        //当前用户的待办任务不唯一，抛出异常，需要TaskID唯一界定
                        var e = new WorkflowException("当前流程有多个运行节点，但没有TaskID传入，状态异常！");
                        LogManager.RecordLog("获取当前运行节点信息异常", LogEventType.Exception, LogPriority.Normal, null, e);
                        throw e;
                    }
                }
            }
            else
            {
                //当前没有运行状态的节点存在，流程不存在，或者已经结束或取消
                var e = new WorkflowException("当前流程没有运行节点，状态异常！");
                LogManager.RecordLog("获取当前运行节点信息异常", LogEventType.Exception, LogPriority.Normal, null, e);
                throw e;
            }
            return activityInstance;
        }

        /// <summary>
        /// 判断任务所属
        /// </summary>
        /// <param name="entity">活动实例</param>
        /// <param name="userID">用户ID</param>
        /// <returns>标识</returns>
        public bool IsMineTask(ActivityInstanceEntity entity,
            string userID)
        {
            bool isMine = entity.AssignedToUserIDs.Contains(userID.ToString());
            return isMine;
        }

        /// <summary>
        /// 获取活动实例列表
        /// </summary>
        /// <param name="processInstanceID">流程实例ID</param>
        /// <returns>活动实例列表</returns>
        public IList<ActivityInstanceEntity> GetActivityInstances(int processInstanceID)
        {

            var instanceList = _activityInstanceEntityRepository.GetList
                (e => e.ProcessInstanceID == processInstanceID);

            return instanceList;
        }

        /// <summary>
        /// 活动实例列表
        /// </summary>
        /// <param name="appInstanceID">应用实例ID</param>
        /// <param name="processGUID">流程GUID</param>
        /// <param name="activityGUID">活动GUID</param>
        /// <returns>活动实例列表</returns>
        public IList<ActivityInstanceEntity> GetActivityInstance(string appInstanceID,
            string processGUID,
            string activityGUID)
        {
            //var sql = @"SELECT * FROM WfActivityInstance 
            //            WHERE AppInstanceID = @appInstanceID 
            //                AND ProcessGUID = @processGUID
            //                AND ActivityGUID = @activityGUID
            //                ORDER BY ID DESC";

            var instanceList = _activityInstanceEntityRepository.GetList(e => e.AppInstanceID == appInstanceID
                    && e.ProcessGUID == processGUID
                    && e.ActivityGUID == activityGUID, "Id DESC", (int?)null, (string[])null)
                .ToList();

            return instanceList;

        }

        /// <summary>
        /// 获取运行状态的活动实例
        /// </summary>
        /// <param name="processInstanceID">流程实例ID</param>
        /// <param name="activityGUID">活动GUID</param>
        
        /// <returns>活动实例</returns>
        public ActivityInstanceEntity GetActivityRunning(int processInstanceID,
            string activityGUID)
        {
            return GetActivityByState(processInstanceID,
                activityGUID,
                ActivityStateEnum.Running);
        }

        /// <summary>
        /// 根据状态获取活动实例
        /// </summary>
        /// <param name="processInstanceID">流程实例ID</param>
        /// <param name="activityGUID">活动GUID</param>
        /// <param name="activityState">活动状态</param>
        /// <returns>活动实例</returns>
        public ActivityInstanceEntity GetActivityByState(int processInstanceID,
            string activityGUID,
            ActivityStateEnum activityState)
        {
            //activityState: 4-completed（完成）
            //var sql = @"SELECT * FROM WfActivityInstance 
            //            WHERE ProcessInstanceID = @processInstanceID 
            //                AND ActivityGUID = @activityGUID 
            //                AND ActivityState = @state
            //            ORDER BY ID DESC";
            ActivityInstanceEntity entity = null;
            var instanceList = _activityInstanceEntityRepository.GetList(
                    e => e.ProcessInstanceID == processInstanceID
                         && e.ActivityGUID == activityGUID
                         && e.ActivityState == activityState, "Id DESC", (int?)null, (string[])null)

                .ToList();
            if (instanceList != null && instanceList.Count == 1) entity = instanceList[0];

            return entity;
        }

        /// <summary>
        /// 获取完成状态的活动实例
        /// </summary>
        /// <param name="processInstanceID">流程实例ID</param>
        /// <param name="activityGUID">活动GUID</param>
        /// <returns>活动实例实体</returns>
        public ActivityInstanceEntity GetActivityCompleted(int processInstanceID,
            string activityGUID)
        {
            return GetActivityByState(processInstanceID, activityGUID, ActivityStateEnum.Completed);

        }

        /// <summary>
        /// 由任务ID获取活动实例信息
        /// </summary>
        /// <param name="taskID">任务ID</param> 
        /// <returns>活动实例实体</returns>
        public ActivityInstanceEntity GetByTask(int taskID)
        {
            //var sql = @"SELECT 
            //                AI.* 
            //            FROM WfActivityInstance AI
            //            INNER JOIN WfTasks T ON AI.ID = T.ActivityInstanceID
            //            WHERE T.ID = @taskID";


            var info = _activityInstanceEntityRepository.Get(x => x.Tasks.Any(y => y.ActivityInstanceID == x.Id));
            return info;
        }

        /// <summary>
        /// 获取流程实例中运行的活动节点
        /// </summary>
        /// <param name="appInstanceID">应用实例ID</param>
        /// <param name="processGUID">流程GUID</param>
        /// <returns>活动实例列表</returns>
        public IEnumerable<ActivityInstanceEntity> GetRunningActivityInstanceList(string appInstanceID,
            string processGUID)
        {
            //var sql = @"SELECT 
            //                    AI.* 
            //                FROM WfActivityInstance AI
            //                INNER JOIN WfProcessInstance PI 
            //                    ON AI.ProcessInstanceID = PI.ID
            //                WHERE (AI.ActivityState=1 OR AI.ActivityState=2)
            //                    AND PI.ProcessState = 2 
            //                    AND AI.AppInstanceID = @appInstanceID 
            //                    AND AI.ProcessGUID = @processGUID";

            var list = _activityInstanceEntityRepository.GetList(x => 
            x.ProcessInstance.ProcessState == ProcessStateEnum.Running && x.AppInstanceID == appInstanceID && x.ProcessGUID == processGUID
            && (x.ActivityState ==  ActivityStateEnum.Ready || x.ActivityState ==  ActivityStateEnum.Running));

            return list;
        }

        /// <summary>
        /// 获取已经运行完成的节点
        /// </summary>
        /// <param name="appInstanceID">应用实例ID</param>
        /// <param name="processGUID">流程GUID</param>
        /// <returns></returns>
        public List<ActivityInstanceEntity> GetCompletedActivityInstanceList(string appInstanceID,
            string processGUID)
        {
            //activityState: 4-completed（完成）
            //var sql = @"SELECT 
            //                    AI.* 
            //                FROM WfActivityInstance AI
            //                INNER JOIN WfProcessInstance PI 
            //                    ON AI.ProcessInstanceID = PI.ID
            //                WHERE PI.ProcessState = 2 
            //                    AND AI.AppInstanceID = @appInstanceID 
            //                    AND AI.ProcessGUID = @processGUID
            //                    AND AI.ActivityState = 4";


            var list = _activityInstanceEntityRepository.GetList(x => x.ProcessInstance.ProcessState == ProcessStateEnum.Running && x.AppInstanceID == appInstanceID && x.ProcessGUID == processGUID
            && x.ActivityState ==  ActivityStateEnum.Completed).ToList();

            return list;
        }

        /// <summary>
        /// 获取主节点下已经完成的子节点列表
        /// </summary>
        /// <param name="mainActivityInstanceID">主活动实例ID</param>
        /// <returns></returns>
        public List<ActivityInstanceEntity> GetCompletedMultipleInstanceList(int mainActivityInstanceID)
        {
            //activityState: 4-completed（完成）
            //var sql = @"SELECT 
            //                    AI.* 
            //                FROM WfActivityInstance AI
            //                INNER JOIN WfProcessInstance PI 
            //                    ON AI.ProcessInstanceID = PI.ID
            //                WHERE PI.ProcessState = 2 
            //                    AND MIHostActivityInstanceID = @mainActivityInstanceID
            //                    AND AI.ActivityState = 4";


            var list = _activityInstanceEntityRepository.GetList(x => x.ProcessInstance.ProcessState == ProcessStateEnum.Running && x.MIHostActivityInstanceID == mainActivityInstanceID && x.ActivityState ==  ActivityStateEnum.Completed).ToList();

            return list;
        }

        /// <summary>
        /// 判断用户是否是分配下来任务的用户
        /// </summary>
        /// <param name="entity">实体</param>
        /// <param name="userID">用户ID</param>
        /// <returns>标识</returns>
        private bool IsAssignedUserInActivityInstance(ActivityInstanceEntity entity,
            int userID)
        {
            var assignedToUsers = entity.AssignedToUserIDs;
            var userList = assignedToUsers.Split(',');
            var single = userList.FirstOrDefault<string>(a => a == userID.ToString());
            if (!string.IsNullOrEmpty(single))
                return true;
            else
                return false;
        }


        /// <summary>
        /// 获取会签节点的多实例节点
        /// </summary>
        /// <param name="mainActivityInstanceID">会签节点</param>
        /// <param name="processInstanceID">流程实例ID</param>
        /// <param name="activityState">活动状态</param>
        /// <returns>活动实例列表</returns>
        public List<ActivityInstanceEntity> GetActivityMulitipleInstanceWithState(int mainActivityInstanceID, int processInstanceID, ActivityStateEnum activityState)
        {
            //activityState: 1-ready（准备）, 2-running（）运行；
            //var sql = @"SELECT 
            //                    * 
            //                FROM WfActivityInstance 
            //                WHERE MIHostActivityInstanceID = @activityInstanceID 
            //                    AND processInstanceID = @processInstanceID
            //                    AND ActivityState = @activityState 
            //                ORDER BY CompleteOrder";
            var instanceList = _activityInstanceEntityRepository.GetList(e => e.MIHostActivityInstanceID == mainActivityInstanceID
                && e.ProcessInstanceID == processInstanceID
                && e.ActivityState == activityState)
                .OrderBy(e => e.CompleteOrder)
                .ToList();
            return instanceList;
        }


        /// <summary>
        /// 获取会签节点的多实例节点
        /// </summary>
        /// <param name="mainActivityInstanceID">会签节点</param>
        /// <param name="processInstanceID">流程实例ID</param>

        /// <returns>活动实例列表</returns>
        public List<ActivityInstanceEntity> GetActivityMultipleInstance(int mainActivityInstanceID,
            int processInstanceID)
        {
            //var sql = @"SELECT 
            //                    * 
            //                FROM WfActivityInstance 
            //                WHERE MIHostActivityInstanceID = @activityInstanceID 
            //                    AND processInstanceID = @processInstanceID
            //                ORDER BY CompleteOrder";

            var instanceList = _activityInstanceEntityRepository.GetList(e => e.MIHostActivityInstanceID == mainActivityInstanceID
                    && e.ProcessInstanceID == processInstanceID)
                .OrderBy(e => e.CompleteOrder)
                .ToList();
            return instanceList;
        }

        /// <summary>
        /// 获取多实例主节点下的子节点列表
        /// </summary>
        /// <param name="mainActivityInstanceID">主节点活动实例ID</param>
        /// <param name="processInstanceID">流程实例ID</param>
        /// <param name="activityState">活动状态</param>
        /// <returns>活动实例列表</returns>
        public List<ActivityInstanceEntity> GetActivityMultipleInstance(int mainActivityInstanceID, int processInstanceID, ActivityStateEnum activityState)
        {
            return GetActivityMulitipleInstanceWithState(mainActivityInstanceID,
                processInstanceID,
                activityState
                );
        }

        /// <summary>
        /// 查询实例节点的前置节点
        /// </summary>
        /// <param name="mainActivityInstanceID"></param>
        /// <param name="activityInstanceID"></param>
        /// <param name="completeOrder"></param>
        /// <returns></returns>
        public ActivityInstanceEntity GetPreviousOfMultipleInstanceNode(int mainActivityInstanceID,
            int activityInstanceID,
            double completeOrder)
        {
            //var whereSql = @"SELECT * FROM WfActivityInstance
            //                WHERE MIHostActivityInstanceID = @mainActivityInstanceID
            //                    AND CompleteOrder = @completeOrder-1
            //                    AND ActivityState=@activityState
            //                ORDER BY ID DESC
            //                ";
 
            var entity = _activityInstanceEntityRepository.Get(e => e.MIHostActivityInstanceID == mainActivityInstanceID  && e.CompleteOrder == completeOrder - 1 
            && e.ActivityState == ActivityStateEnum.Completed);
            //"Id DESC"

            return entity;
            
        }
        /// <summary>
        /// 查询分支实例的个数
        /// </summary>
        /// <param name="splitActivityGUID">节点GUID</param>
        /// <param name="processInstanceID">流程实例ID</param>
        /// <returns>网关实例数目</returns>
        public int GetInstanceGatewayCount(string splitActivityGUID,
            int processInstanceID)
        {
            //var whereSql = @"SELECT 
            //                    * 
            //                FROM wftransitioninstance
            //                WHERE processinstanceid=@processinstanceId 
            //                    AND fromactivityguid=@fromActivityGUID";

            var instanceList = _transitionInstanceEntityRepository.Count(e => e.ProcessInstanceID == processInstanceID
                && e.FromActivityGUID == splitActivityGUID);
            return instanceList;

        }
        #endregion

        #region 创建活动实例
        /// <summary>
        /// 创建活动实例的对象
        /// </summary>
        /// <param name="appName">应用名称</param>
        /// <param name="appInstanceID">应用实例ID</param>
        /// <param name="processInstanceID">流程实例ID</param>
        /// <param name="activity">活动</param>
        /// <param name="runner">运行者</param>
        /// <returns>活动实例实体</returns>
        public ActivityInstanceEntity CreateActivityInstanceObject(string appName,
            string appInstanceID,
            int processInstanceID,
            ActivityEntity activity,
            WfAppRunner runner)
        {
            ActivityInstanceEntity instance = new ActivityInstanceEntity();
            instance.ActivityGUID = activity.ActivityGUID;
            instance.ActivityName = activity.ActivityName;
            instance.ActivityType = activity.ActivityType;
            instance.WorkItemType = activity.WorkItemType;
            instance.GatewayDirectionTypeID = activity.GatewayDirectionType;
            instance.ProcessGUID = activity.ProcessGUID;
            instance.AppName = appName;
            instance.AppInstanceID = appInstanceID;
            instance.ProcessInstanceID = processInstanceID;
            instance.TokensRequired = 1;
            instance.TokensHad = 1;
            instance.CreatedUserId =int.Parse( runner.UserID);
            instance.CreatedUserName = runner.UserName;
            instance.CreatedTime = System.DateTime.Now;
            instance.ActivityState = ActivityStateEnum.Ready;
            instance.CanRenewInstance = 0;

            return instance;
        }

        /// <summary>
        /// 根据主节点复制子节点
        /// </summary>
        /// <param name="main">活动实例</param>
        /// <returns>活动实例</returns>
        public ActivityInstanceEntity CreateActivityInstanceObject(ActivityInstanceEntity main)
        {
            ActivityInstanceEntity instance = new ActivityInstanceEntity();
            instance.ActivityGUID = main.ActivityGUID;
            instance.ActivityName = main.ActivityName;
            instance.ActivityType = main.ActivityType;
            instance.WorkItemType = main.WorkItemType;
            instance.GatewayDirectionTypeID = main.GatewayDirectionTypeID;
            instance.ProcessGUID = main.ProcessGUID;
            instance.AppName = main.AppName;
            instance.AppInstanceID = main.AppInstanceID;
            instance.ProcessInstanceID = main.ProcessInstanceID;
            instance.TokensRequired = 1;
            instance.TokensHad = 1;
            instance.CreatedUserId = main.CreatedUserId;
            instance.CreatedUserName = main.CreatedUserName;
            instance.CreatedTime = System.DateTime.Now;
            instance.ActivityState = ActivityStateEnum.Ready;
            instance.CanRenewInstance = 0;

            return instance;
        }

        /// <summary>
        /// 创建活动实例的对象
        /// </summary>
        /// <param name="appName">应用名称</param>
        /// <param name="appInstanceID">应用实例ID</param>
        /// <param name="processInstanceID">流程实例ID</param>
        /// <param name="activity">活动</param>
        /// <param name="backwardType">退回类型</param>
        /// <param name="backSrcActivityInstanceID">退回源活动实例ID</param>
        /// <param name="runner">执行者</param>
        /// <returns>活动实例</returns>
        public ActivityInstanceEntity CreateBackwardActivityInstanceObject(string appName,
            string appInstanceID,
            int processInstanceID,
            ActivityEntity activity,
            BackwardTypeEnum backwardType,
            int backSrcActivityInstanceID,
            WfAppRunner runner)
        {
            ActivityInstanceEntity instance = new ActivityInstanceEntity();
            instance.ActivityGUID = activity.ActivityGUID;
            instance.ActivityName = activity.ActivityName;
            instance.ActivityType = activity.ActivityType;
            instance.WorkItemType = activity.WorkItemType;
            instance.GatewayDirectionTypeID = activity.GatewayDirectionType;
            instance.ProcessGUID = activity.ProcessGUID;
            instance.AppName = appName;
            instance.AppInstanceID = appInstanceID;
            instance.ProcessInstanceID = processInstanceID;
            instance.BackwardType = backwardType;
            instance.BackSrcActivityInstanceID = backSrcActivityInstanceID;
            instance.TokensRequired = 1;
            instance.TokensHad = 1;
            instance.CreatedUserId =int.Parse( runner.UserID);
            instance.CreatedUserName = runner.UserName;
            instance.CreatedTime = System.DateTime.Now;
            instance.ActivityState = ActivityStateEnum.Ready;
            instance.CanRenewInstance = 0;

            return instance;
        }

        /// <summary>
        /// 更新活动节点的Token数目
        /// </summary>
        /// <param name="activityInstanceID">活动实例ID</param>
        /// <param name="runner">运行者</param>
        
        public void IncreaseTokensHad(int activityInstanceID,
            WfAppRunner runner)
        {
            ActivityInstanceEntity activityInstance = GetById(activityInstanceID);
            activityInstance.TokensHad += 1;

            Update(activityInstance);
        }
        #endregion

        #region 活动实例中间状态设置

        /// <summary>
        /// 活动实例被读取
        /// </summary>
        /// <param name="activityInstanceID">活动实例ID</param>
        /// <param name="runner">运行者</param>
        public void SetActivityRead(int activityInstanceID, WfAppRunner runner)
        {
            SetActivityState(activityInstanceID, ActivityStateEnum.Running, runner);
        }

        /// <summary>
        /// 撤销活动实例
        /// </summary>
        /// <param name="activityInstanceID">活动实例ID</param>
        /// <param name="runner">运行者</param>
        public void Withdraw(int activityInstanceID, WfAppRunner runner)
        {
            SetActivityState(activityInstanceID, ActivityStateEnum.Withdrawed, runner);
        }

        /// <summary>
        /// 退回活动实例
        /// </summary>
        /// <param name="activityInstanceID">活动实例ID</param>
        /// <param name="runner">运行者</param>
        public void SendBack(int activityInstanceID, WfAppRunner runner)
        {
            SetActivityState(activityInstanceID, ActivityStateEnum.Sendbacked, runner);
        }

        /// <summary>
        /// 设置活动实例状态
        /// </summary>
        /// <param name="activityInstanceID">活动实例ID</param>
        /// <param name="nodeState">节点状态</param>
        /// <param name="runner">运行者</param>

        private void SetActivityState(int activityInstanceID,
            ActivityStateEnum nodeState,
            WfAppRunner runner)
        {
            var entity = GetById(activityInstanceID);
            entity.ActivityState = nodeState;
            entity.ModifiedUserId = runner.UserID.ToInt();
            entity.LastUpdatedByUserName = runner.UserName;
            entity.ModifiTime = System.DateTime.Now;
            _activityInstanceEntityRepository.Update(entity);

            _activityInstanceEntityRepository.Context.Commit();
        }

        /// <summary>
        /// 活动实例完成
        /// </summary>
        /// <param name="activityInstanceID">活动实例ID</param>
        /// <param name="runner">运行者</param>
        
        public void Complete(int activityInstanceID,
            WfAppRunner runner)
        {
            var activityInstance = GetById(activityInstanceID);
            activityInstance.ActivityState = ActivityStateEnum.Completed;
            activityInstance.ModifiedUserId = runner.UserID.ToInt();
            activityInstance.LastUpdatedByUserName = runner.UserName;
            activityInstance.ModifiTime = System.DateTime.Now;
            activityInstance.EndedByUserID = runner.UserID;
            activityInstance.EndedByUserName = runner.UserName;
            activityInstance.EndedDateTime = System.DateTime.Now;

            Update(activityInstance);
        }
        #endregion

        #region 活动实例记录维护
        /// <summary>
        /// 插入活动实例
        /// </summary>
        /// <param name="entity">实体</param>
        
        /// <returns>新的自增长ID键值</returns>
        public int Insert(ActivityInstanceEntity entity)
        {
            //SET ActivityName When It Is NULL
            if (entity.ActivityType == ActivityTypeEnum.GatewayNode
                && string.IsNullOrEmpty(entity.ActivityName))
            {
                entity.ActivityName = "GATEWAY";
            }
 
           _activityInstanceEntityRepository.Add(entity);
            _activityInstanceEntityRepository.Context.Commit();

            return entity.Id ;
        }

        /// <summary>
        /// 更新活动实例
        /// </summary>
        /// <param name="entity">活动实例实体</param>
        
        public void Update(ActivityInstanceEntity entity)
        {
            _activityInstanceEntityRepository.Update(entity);
            _activityInstanceEntityRepository.Context.Commit();
        }

        /// <summary>
        /// 更新会签节点中未办理完成的节点状态
        /// </summary>
        /// <param name="mainActivityInstanceID">主节点ID</param>
        /// <param name="runner">执行者</param>
        public void CancelUnCompletedMultipleInstance(int mainActivityInstanceID, WfAppRunner runner)
        {
            //var sql = @"UPDATE 
            //                WfActivityInstance 
            //            SET ActivityState=@activityState,
            //                ModifiedUserId=@lastUpdatedByUserID,
            //                LastUpdatedByUserName=@lastUpdatedByUserName,
            //                ModifiTime=@lastUpdatedDateTime 
            //            WHERE MIHostActivityInstanceID=@mainActivityInstanceID 
            //                AND ActivityState in (1,2,5) ";
            var ids = new[] { ActivityStateEnum.Ready, ActivityStateEnum.Running, ActivityStateEnum.Suspended };
            var list = _activityInstanceEntityRepository .GetList(e => e.MIHostActivityInstanceID == mainActivityInstanceID && ids.Contains(e.ActivityState))
                .ToList();

            list.ForEach(a =>
            {
                a.ActivityState = ActivityStateEnum.Cancelled;
                a.ModifiedUserId = runner.UserID.ToInt();
                a.LastUpdatedByUserName = runner.UserName;
                a.ModifiTime = System.DateTime.Now;
            });
            _activityInstanceEntityRepository.Context.Commit();
        }

        /// <summary>
        /// 撤销主节点及其下面的多实例子节点
        /// </summary>
        /// <param name="mainActivityInstanceID">主节点ID</param>
        /// <param name="runner">执行者</param>
        
        public void WithdrawMainIncludedChildNodes(int mainActivityInstanceID,
            WfAppRunner runner)
        {
            //先更新主节点状态为撤销状态
            SetActivityState(mainActivityInstanceID, ActivityStateEnum.Withdrawed, runner);

            //再更新主节点下的多实例子节点状态为撤销状态
            WithdrawMultipleInstance(mainActivityInstanceID, runner);
        }

        /// <summary>
        /// 更新会签办理节点的节点状态
        /// </summary>
        /// <param name="mainActivityInstanceID">主节点ID</param>
        /// <param name="runner">执行者</param>

        private void WithdrawMultipleInstance(int mainActivityInstanceID,
            WfAppRunner runner)
        {
            //var sql = @"UPDATE 
            //                WfActivityInstance 
            //            SET ActivityState=@activityState, 
            //                ModifiedUserId=@lastUpdatedByUserID,
            //                LastUpdatedByUserName=@lastUpdatedByUserName,
            //                ModifiTime=@lastUpdatedDateTime
            //            WHERE MIHostActivityInstanceID=@mainActivityInstanceID
            //                AND (ActivityState=1 OR ActivityState=5)";      //准备或挂起状态的节点可以撤销
            var list = _activityInstanceEntityRepository.GetList(e => e.MIHostActivityInstanceID == mainActivityInstanceID)
                .ToList();

            list.ForEach(a =>
            {
                a.ActivityState = ActivityStateEnum.Withdrawed;
                a.ModifiedUserId = runner.UserID.ToInt();
                a.LastUpdatedByUserName = runner.UserName;
                a.ModifiTime = System.DateTime.Now;
            });
            _activityInstanceEntityRepository.Context.Commit();
        }

        /// <summary>
        /// 重新使节点处于挂起状态
        /// 说明：会签最后一个子节点撤销时候用到
        /// </summary>
        /// <param name="activityInstanceID">活动实例节点ID</param>
        /// <param name="runner">执行者</param>
        
        public void Resuspend(int activityInstanceID,
            WfAppRunner runner)
        {
            SetActivityState(activityInstanceID, ActivityStateEnum.Suspended, runner);
        }

        /// <summary>
        /// 删除活动实例
        /// </summary>
        /// <param name="activityInstanceID">活动实例ID</param>

        public void Delete(int activityInstanceID)
        {
            var info = _activityInstanceEntityRepository.Get(activityInstanceID);
            _activityInstanceEntityRepository.Remove(info);
            _activityInstanceEntityRepository.Context.Commit();
        }
        #endregion
    }
}
